package mx.itesm.rmroman.proyectojuegomavi;

import android.hardware.SensorManager;
import android.util.Log;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.FixtureDef;

import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.sprite.Sprite;
import org.andengine.extension.physics.box2d.PhysicsConnector;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.input.sensor.acceleration.AccelerationData;
import org.andengine.input.sensor.acceleration.IAccelerationListener;
import org.andengine.opengl.texture.ITexture;
import org.andengine.opengl.texture.bitmap.AssetBitmapTexture;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.TextureRegionFactory;

import java.io.IOException;
import java.util.ArrayList;

/**
 * La escena que muestra información del juego
 * @author Roberto Martínez Román
 */
public class EscenaFisica extends EscenaBase implements IAccelerationListener
{
    private float tiempo=0;
    private PhysicsWorld mundoFisico;

    // Esto debería estar en AdministradorRecursos
    private ITexture texturaSplash;
    public ITextureRegion regionSplash;

    private ITexture texturaRoca;
    public ITextureRegion regionRoca;

    private ITexture texturaMario;
    public ITextureRegion regionMario;

    // Objetos
    private ArrayList<Sprite> lista;

    // Personaje
    private Sprite mario;
    private Body cuerpoMario;

    @Override
    public void crearEscena() {

        cargarRecursos();

        mundoFisico = new PhysicsWorld(new Vector2(0, -2*SensorManager.GRAVITY_EARTH),false);
        registerUpdateHandler(mundoFisico);

        admRecursos.engine.enableAccelerationSensor(admRecursos.actividadJuego,this);

        lista = new ArrayList<>();

        agregarFondo();
        agregarObjetos();
        agregarPersonaje();
    }

    private void agregarPersonaje() {
        final FixtureDef fd = PhysicsFactory.createFixtureDef(1,0.3f,0.5f);

        // El personaje
        mario = new Sprite(ControlJuego.ANCHO_CAMARA/2, ControlJuego.ALTO_CAMARA,
                regionMario,admRecursos.vbom);
        cuerpoMario = PhysicsFactory.createBoxBody(mundoFisico,mario, BodyDef.BodyType.DynamicBody,fd);
        cuerpoMario.setFixedRotation(true);
        mundoFisico.registerPhysicsConnector(new PhysicsConnector(mario, cuerpoMario, true, true));
        attachChild(mario);
    }

    private void cargarRecursos() {
        try {
            // Carga la imagen de fondo de la pelota
            texturaSplash = new AssetBitmapTexture(admRecursos.actividadJuego.getTextureManager(),
                    admRecursos.actividadJuego.getAssets(), "fisica/pelota.png");
            regionSplash = TextureRegionFactory.extractFromTexture(texturaSplash);
            texturaSplash.load();
            // Carga la imagen de la plataforma
            texturaRoca = new AssetBitmapTexture(admRecursos.actividadJuego.getTextureManager(),
                    admRecursos.actividadJuego.getAssets(), "fisica/roca.jpg");
            regionRoca = TextureRegionFactory.extractFromTexture(texturaRoca);
            texturaRoca.load();
            // Carga la imagen de mario :)
            texturaMario = new AssetBitmapTexture(admRecursos.actividadJuego.getTextureManager(),
                    admRecursos.actividadJuego.getAssets(), "fisica/mario.png");
            regionMario = TextureRegionFactory.extractFromTexture(texturaMario);
            texturaMario.load();
        } catch (IOException e) {
            Log.d("cargarRecursosSplash", "No se puede cargar el roca");
        }
    }

    private void agregarObjetos() {
        final FixtureDef fd = PhysicsFactory.createFixtureDef(1,0.3f,0.5f);

        // Este objeto cae
        Rectangle objeto = new Rectangle(ControlJuego.ANCHO_CAMARA/2, ControlJuego.ALTO_CAMARA,
                50,50,admRecursos.vbom);
        objeto.setColor(0,1,0);
        Body cuerpo = PhysicsFactory.createBoxBody(mundoFisico,objeto, BodyDef.BodyType.DynamicBody,fd);
        cuerpo.setLinearDamping(1);
        cuerpo.setFixedRotation(true);
        cuerpo.setUserData(objeto);
        mundoFisico.registerPhysicsConnector(new PhysicsConnector(objeto, cuerpo, true, true));
        attachChild(objeto);
        agregarPlataformas(fd);
    }

    // Agrega algunas plataformas al mundo
    private void agregarPlataformas(FixtureDef fd) {

        Sprite base = new Sprite(ControlJuego.ANCHO_CAMARA/2, ControlJuego.ALTO_CAMARA/16,
                regionRoca,admRecursos.vbom);
        Body cuerpoBase = PhysicsFactory.createBoxBody(mundoFisico, base, BodyDef.BodyType.StaticBody, fd);
        attachChild(base);

        Sprite media = new Sprite(ControlJuego.ANCHO_CAMARA/4, ControlJuego.ALTO_CAMARA/2,
                regionRoca,admRecursos.vbom);
        Body cuerpoMedio = PhysicsFactory.createBoxBody(mundoFisico, media, BodyDef.BodyType.StaticBody, fd);
        attachChild(media);

        Sprite alta = new Sprite(3*ControlJuego.ANCHO_CAMARA/4, 3*ControlJuego.ALTO_CAMARA/8,
                regionRoca,admRecursos.vbom);
        Body cuerpoAlto = PhysicsFactory.createBoxBody(mundoFisico, alta, BodyDef.BodyType.StaticBody, fd);
        attachChild(alta);
    }

    private void agregarFondo() {
        setBackground(new Background(0.9f,0.9f,0.9f));
        setBackgroundEnabled(true);
    }


    // El ciclo principal de la escena
    @Override
    protected void onManagedUpdate(float pSecondsElapsed) {
        super.onManagedUpdate(pSecondsElapsed);

        tiempo += pSecondsElapsed;
        if ( tiempo>0.5f ) {
            tiempo = 0;
            agregarNuevoObjeto();
        }
        verificarObjetosSalen();
    }

    private void verificarObjetosSalen() {
        for(int i=lista.size()-1; i>=0; i--) {
            Sprite sp = lista.get(i);
            if ( sp.getY()< -32 || sp.getY()>ControlJuego.ALTO_CAMARA + 32) {
                sp.detachSelf();
                lista.remove(i);
            }
        }
    }

    private void agregarNuevoObjeto() {
        final FixtureDef fd = PhysicsFactory.createFixtureDef(1, 0.6f, 0.5f);

        float x = (float)(Math.random()* ControlJuego.ANCHO_CAMARA);
        float y = ControlJuego.ALTO_CAMARA;
        // Este objeto cae
        Sprite objeto = new Sprite(x,y,regionSplash,admRecursos.vbom);
        objeto.setColor(0,1,0);
        Body cuerpo = PhysicsFactory.createCircleBody(mundoFisico, objeto, BodyDef.BodyType.DynamicBody, fd);
        cuerpo.setUserData(objeto);
        mundoFisico.registerPhysicsConnector(new PhysicsConnector(objeto, cuerpo, true, true));
        attachChild(objeto);
        lista.add(objeto);
    }


    // El usuario oprime el botón de BACK; regresar al menú principal
    @Override
    public void onBackKeyPressed() {
        // Regresar al MENU principal
        admRecursos.engine.disableAccelerationSensor(admRecursos.actividadJuego);
        admEscenas.crearEscenaMenu();
        admEscenas.setEscena(TipoEscena.ESCENA_MENU);
        admEscenas.liberarEscenaFisica();
    }

    @Override
    public TipoEscena getTipoEscena() {
        return TipoEscena.ESCENA_FISICA;
    }

    @Override
    public void liberarEscena() {
        this.detachSelf();      // La escena misma se deconecta del engine
        this.dispose();         // Libera la memoria
    }

    @Override
    public void onAccelerationAccuracyChanged(AccelerationData pAccelerationData) {
    }

    @Override
    public void onAccelerationChanged(AccelerationData pAccelerationData) {
        mundoFisico.setGravity(new Vector2(pAccelerationData.getX(),pAccelerationData.getY()*2));
    }

}
